<template>
  <div class="btn-box">
    <div
      class="btn-item-box"
      v-for="(item, index) of state.picList"
      :key="index"
      :title="item.title"
      @click="btnClick(item, index)"
    >
      <img style="width: 60%; height: 60%" :src="getPic(item, index)" />
      <!-- 环境盒子 -->
      <div
        class="btn-more-box"
        v-if="item.title == '环境效果' && state.envBoxShow"
      >
        <!-- 盒子标题 -->
        <div class="more-box-title">环境效果</div>
        <!-- 盒子内容 -->
        <div class="more-box-content">
          <div
            class="more-box-content-item"
            v-for="(item, index) of envList"
            :key="index"
            @click.stop="getEnvEff(item)"
          >
            <div class="more-box-content-item2" :class="getEnvClass(item)">
              <img
                style="width: 80%; height: 80%"
                :src="item.picUrl"
                :title="item.title"
              />
            </div>
            <div class="more-box-content-title" :class="getEnvTextClass(item)">
              {{ item.title }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
  
  <script setup>
import { reactive, onMounted } from "vue";
import * as Cesium from "cesium";

import { useStore } from "vuex";
let store = useStore();

const envList = [
  {
    title: "降雨效果",
    picUrl: "src/assets/images/toolpic/rain-pic.png",
  },
  {
    title: "降雪效果",
    picUrl: "src/assets/images/toolpic/snow-pic.png",
  },
];

let state = reactive({
  envBoxShow: false,
  picList: [
    {
      title: "初始视角",
      pic: "src/assets/images/toolpic/home.png",
      picActive: "src/assets/images/toolpic/home-active.png",
    },
    {
      title: "图层管理",
      pic: "src/assets/images/toolpic/layer.png",
      picActive: "src/assets/images/toolpic/layer-active.png",
    },
    {
      title: "环境效果",
      pic: "src/assets/images/toolpic/envir.png",
      picActive: "src/assets/images/toolpic/envir-active.png",
    },
    {
      title: "获取当前视角信息",
      pic: "src/assets/images/toolpic/position.png",
    },
  ],
  rainStateShow: false,
  snowStateShow: false,
});

// 获取图片
const getPic = (item, index) => {
  let url = state.picList[index].pic;
  if (item.title == "图层管理") {
    if (store.state.layerControlShow) {
      url = state.picList[index].picActive;
    }
  } else if (item.title == "环境效果") {
    if (state.envBoxShow) {
      url = state.picList[index].picActive;
    } else {
      url = state.picList[index].pic;
    }
  }
  return url;
};

// 工具箱点击
const btnClick = (item, index) => {
  if (item.title == "图层管理") {
    store.state.layerControlShow = !store.state.layerControlShow;
  } else if (item.title == "初始视角") {
    goHomeView();
  } else if (item.title == "环境效果") {
    state.envBoxShow = !state.envBoxShow;
  } else if (item.title == "获取当前视角信息") {
    getNowInfo();
  } else {
    console.log(item.title, index);
  }
};
// 降雨状态
let rainState = null;
let snowState = null;
// 获取环境效果
function getEnvEff(item) {
  if (item.title == "降雨效果") {
    if (rainState) {
      removeRain();
    } else {
      addRainEff();
    }
  } else if (item.title == "降雪效果") {
    if (snowState) {
      removeSnow();
    } else {
      addSnowEff();
    }
  }
}

// 激活环境效果
function getEnvClass(item) {
  if (item.title == "降雨效果") {
    if (state.rainStateShow) {
      return "btn-active";
    } else {
      return "";
    }
  } else if (item.title == "降雪效果") {
    if (state.snowStateShow) {
      return "btn-active";
    } else {
      return "";
    }
  }
}

// 激活环境效果字体
function getEnvTextClass(item) {
  if (item.title == "降雨效果") {
    if (state.rainStateShow) {
      return "btn-text-active";
    } else {
      return "";
    }
  } else if (item.title == "降雪效果") {
    if (state.snowStateShow) {
      return "btn-text-active";
    } else {
      return "";
    }
  }
}

// 添加降雨效果
function addRainEff() {
  // 雨
  const FS_Rain = `uniform sampler2D colorTexture;
      in vec2 v_textureCoordinates;
      uniform float tiltAngle;
      uniform float rainSize;
      uniform float rainSpeed;
      float hash(float x) {
        return fract(sin(x * 133.3) * 13.13);
      }
      out vec4 vFragColor;
      void main(void) {
        float time = czm_frameNumber / rainSpeed;
        vec2 resolution = czm_viewport.zw;
        vec2 uv = (gl_FragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y);
        vec3 c = vec3(.6, .7, .8);
        float a = tiltAngle;
        float si = sin(a), co = cos(a);
        uv *= mat2(co, -si, si, co);
        uv *= length(uv + vec2(0, 4.9)) * rainSize + 1.;
        float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);
        float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;
        c *= v * b;
        vFragColor = mix(texture(colorTexture, v_textureCoordinates), vec4(c, 1), .5);
      }
`;

  let viewer = store.state.viewer;
  let rain = new Cesium.PostProcessStage({
    name: "rain",
    fragmentShader: FS_Rain,
    uniforms: {
      tiltAngle: -0.6, // 倾斜角度
      rainSize: 0.6, // 雨大小
      rainSpeed: 120, //雨速
    },
  });
  viewer.scene.postProcessStages.add(rain);
  rainState = rain;
  state.rainStateShow = true;
}

// 移除雨
function removeRain() {
  let viewer = store.state.viewer;
  state.rainStateShow = false;

  rainState && viewer.scene.postProcessStages.remove(rainState),
    (rainState = null);
}

// 添加降雪效果
function addSnowEff() {
  // 雪
  const FS_Snow = `
      uniform sampler2D colorTexture;
      in vec2 v_textureCoordinates;
      uniform float snowSpeed;
      uniform float snowSize;
      float snow(vec2 uv,float scale) {
        float time=czm_frameNumber/snowSpeed;
        float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;
        uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;
        uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;
        p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);
        k=smoothstep(0.,k,sin(f.x+f.y)*snowSize);
        return k*w;
      }
      out vec4 vFragColor;
      void main(void){
        vec2 resolution=czm_viewport.zw;
        vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
        vec3 finalColor=vec3(0);
        //float c=smoothstep(1.,0.3,clamp(uv.y*.3+.8,0.,.75));
        float c=0.;
        c+=snow(uv,30.)*.0;
        c+=snow(uv,20.)*.0;
        c+=snow(uv,15.)*.0;
        c+=snow(uv,10.);
        c+=snow(uv,8.);
        c+=snow(uv,6.);
        c+=snow(uv,5.);
        finalColor=(vec3(c));
        vFragColor=mix(texture(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);
      }
    `;

  let viewer = store.state.viewer;
  let snow = new Cesium.PostProcessStage({
    name: "snow",
    fragmentShader: FS_Snow,
    uniforms: {
      snowSize: 0.02, // 雨大小
      snowSpeed: 60, //雨速
    },
  });
  viewer.scene.postProcessStages.add(snow);
  snowState = snow;
  state.snowStateShow = true;
}

// 移除雪效果
function removeSnow() {
  let viewer = store.state.viewer;
  state.snowStateShow = false;
  snowState && viewer.scene.postProcessStages.remove(snowState),
    (snowState = null);
}

// 初始视角
function goHomeView() {
  let viewer = store.state.viewer;
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(
      106.64398718792951,
      29.59998330998217,
      1128.629108949175
    ),
    orientation: {
      heading: 0.06371156721431603,
      pitch: -0.2954139485196208,
      roll: 0.00003989348111144153,
    },
    complete: function callback() {
      // 定位完成之后的回调函数
    },
  });
}

// 获取当前视角信息
function getNowInfo() {
  let longitude = Cesium.Math.toDegrees(
    Cesium.Cartographic.fromCartesian(viewer.camera.position).longitude
  );
  let latitude = Cesium.Math.toDegrees(
    Cesium.Cartographic.fromCartesian(viewer.camera.position).latitude
  );
  let height = Cesium.Cartographic.fromCartesian(viewer.camera.position).height;
  let info = longitude + "," + latitude + "," + height;
  console.log("position:" + info);
  console.log(
    "heading/pitch/roll:" +
      viewer.camera.heading +
      "," +
      viewer.camera.pitch +
      "," +
      viewer.camera.roll
  );
}

onMounted(() => {});
</script>
  
  <style scoped>
.btn-box {
  padding: 5px;
}

.btn-item-box {
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 1px solid rgb(0, 72, 253);
  color: #fff;
  border-radius: 10px;
  box-shadow: 0px 0px 20px rgba(0, 72, 253, 0.5);
  background: radial-gradient(rgba(58, 64, 79, 0), rgba(58, 64, 79, 1));
  user-select: none;
  cursor: pointer;
  overflow: hidden;
}

.btn-more-box {
  position: absolute;
  bottom: 0;
  left: -260px;
  width: 250px;
  height: 250px;
  background: radial-gradient(rgba(58, 64, 79, 0), rgba(58, 64, 79, 1));
  box-shadow: 0px 0px 20px rgba(0, 72, 253, 0.5);
  border-radius: 10px;
  overflow: hidden;
  cursor: auto;
  user-select: none;
}

.more-box-title {
  display: flex;
  align-items: center;
  padding: 0 10px;
  height: 40px;
  background: radial-gradient(rgba(58, 64, 79, 0), rgba(0, 72, 253, 0.5));
  color: #fff;
}
.more-box-content {
  display: flex;
  flex-wrap: wrap;
  height: 160px;
  width: 100%;
}

.btn-active {
  border: 2px solid rgba(0, 72, 253, 0.8);
}

.btn-text-active {
  color: rgba(0, 236, 253, 0.86);
}

.more-box-content-item {
  padding: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  width: 60px;
  height: 80px;
}

.more-box-content-item2 {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  cursor: pointer;
}

.more-box-content-title {
  margin-top: 5px;
  font-size: 14px;
}
</style>